// Class Helpers (类助手) 示例
// 演示 Pascal 中类助手的各种用法
program p_34_class_helpers;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式，支持面向对象编程
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils,  // 系统工具单元，包含常用的系统函数
  Classes;   // 类单元，包含TStringList等类

// 定义一个简单的人员类
type
  TPerson = class
  private
    FName: String;
    FAge: Integer;
  public
    constructor Create(const AName: String; AAge: Integer);
    procedure Introduce;
    property Name: String read FName write FName;
    property Age: Integer read FAge write FAge;
  end;

// TPerson类的实现
constructor TPerson.Create(const AName: String; AAge: Integer);
begin
  inherited Create;
  FName := AName;
  FAge := AAge;
  WriteLn('  创建人员: ', FName, ', 年龄: ', FAge);
end;

procedure TPerson.Introduce;
begin
  WriteLn('  大家好，我是 ', FName, '，今年 ', FAge, ' 岁。');
end;

// 为TPerson类定义类助手
type
  TPersonHelper = class helper for TPerson
  public
    // 添加新的方法
    procedure CelebrateBirthday;
    function GetInfo: String;
    
    // 添加计算属性方法
    function IsAdult: Boolean;
    
    // 添加类方法
    class function CreateAnonymous: TPerson;
  end;

// TPersonHelper类助手的实现
procedure TPersonHelper.CelebrateBirthday;
begin
  WriteLn('  ', Self.Name, ' 正在庆祝生日！');
  Self.Age := Self.Age + 1;
  WriteLn('  ', Self.Name, ' 现在 ', Self.Age, ' 岁了。');
end;

function TPersonHelper.GetInfo: String;
begin
  Result := '姓名: ' + Self.Name + ', 年龄: ' + IntToStr(Self.Age);
end;

function TPersonHelper.IsAdult: Boolean;
begin
  Result := Self.Age >= 18;
end;

class function TPersonHelper.CreateAnonymous: TPerson;
begin
  Result := TPerson.Create('匿名', 0);
end;

// 为String类型定义助手
type
  TStringHelper = class helper for String
  public
    function Reverse: String;
    function WordCount: Integer;
    function IsPalindrome: Boolean;
    function ToTitleCase: String;
  end;

// TStringHelper类助手的实现
function TStringHelper.Reverse: String;
var
  i: Integer;
begin
  Result := '';
  for i := Length(Self) downto 1 do
    Result := Result + Self[i];
end;

function TStringHelper.WordCount: Integer;
var
  i: Integer;
  inWord: Boolean;
begin
  Result := 0;
  inWord := False;
  
  for i := 1 to Length(Self) do
  begin
    if (Self[i] <> ' ') and (Self[i] <> #9) then  // 不是空格或制表符
    begin
      if not inWord then
      begin
        Inc(Result);
        inWord := True;
      end;
    end
    else
      inWord := False;
  end;
end;

function TStringHelper.IsPalindrome: Boolean;
var
  cleaned: String;
  i: Integer;
begin
  // 清理字符串，只保留字母并转为小写
  cleaned := '';
  for i := 1 to Length(Self) do
  begin
    if Self[i] in ['a'..'z', 'A'..'Z'] then
      cleaned := cleaned + LowerCase(Self[i]);
  end;
  
  // 检查是否为回文
  Result := cleaned = ReverseString(cleaned);
end;

function TStringHelper.ToTitleCase: String;
var
  i: Integer;
  capitalizeNext: Boolean;
begin
  Result := LowerCase(Self);
  capitalizeNext := True;
  
  for i := 1 to Length(Result) do
  begin
    if Result[i] in ['a'..'z'] then
    begin
      if capitalizeNext then
      begin
        Result[i] := UpCase(Result[i]);
        capitalizeNext := False;
      end;
    end
    else if Result[i] in [' ', '-', '_'] then
      capitalizeNext := True;
  end;
end;

// 为Integer类型定义助手
type
  TIntegerHelper = class helper for Integer
  public
    function IsEven: Boolean;
    function IsOdd: Boolean;
    function Factorial: Int64;
    function ToBinary: String;
    function IsPrime: Boolean;
  end;

// TIntegerHelper类助手的实现
function TIntegerHelper.IsEven: Boolean;
begin
  Result := (Self mod 2) = 0;
end;

function TIntegerHelper.IsOdd: Boolean;
begin
  Result := (Self mod 2) <> 0;
end;

function TIntegerHelper.Factorial: Int64;
var
  i: Integer;
begin
  if Self < 0 then
  begin
    Result := 0;
    Exit;
  end;
  
  Result := 1;
  for i := 2 to Self do
    Result := Result * i;
end;

function TIntegerHelper.ToBinary: String;
var
  n: Integer;
begin
  if Self = 0 then
  begin
    Result := '0';
    Exit;
  end;
  
  Result := '';
  n := Self;
  while n > 0 do
  begin
    if (n mod 2) = 1 then
      Result := '1' + Result
    else
      Result := '0' + Result;
    n := n div 2;
  end;
end;

function TIntegerHelper.IsPrime: Boolean;
var
  i: Integer;
begin
  if Self < 2 then
  begin
    Result := False;
    Exit;
  end;
  
  if Self = 2 then
  begin
    Result := True;
    Exit;
  end;
  
  if (Self mod 2) = 0 then
  begin
    Result := False;
    Exit;
  end;
  
  for i := 3 to Trunc(Sqrt(Self)) step 2 do
  begin
    if (Self mod i) = 0 then
    begin
      Result := False;
      Exit;
    end;
  end;
  
  Result := True;
end;

// 程序主入口
begin
  WriteLn('=== Pascal 类助手示例 ===');
  WriteLn;
  
  // 1. 为自定义类添加助手方法
  WriteLn('1. 为自定义类添加助手方法:');
  var person: TPerson := TPerson.Create('张三', 17);
  try
    person.Introduce;
    WriteLn('  信息: ', person.GetInfo);
    WriteLn('  是成年人: ', person.IsAdult);
    
    WriteLn;
    person.CelebrateBirthday;
    WriteLn('  生日后信息: ', person.GetInfo);
    WriteLn('  是成年人: ', person.IsAdult);
    
    WriteLn;
    // 使用类助手的类方法
    var anonymous: TPerson := TPerson.CreateAnonymous;
    anonymous.Introduce;
    anonymous.Free;
  finally
    person.Free;
  end;
  
  WriteLn;
  
  // 2. 为String类型添加助手方法
  WriteLn('2. 为String类型添加助手方法:');
  var text: String := 'Hello World';
  WriteLn('  原始文本: ', text);
  WriteLn('  反转后: ', text.Reverse);
  WriteLn('  单词数: ', text.WordCount);
  
  var palindrome: String := 'A man a plan a canal Panama';
  WriteLn('  文本: "', palindrome, '"');
  WriteLn('  是回文: ', palindrome.IsPalindrome);
  
  var titleText: String := 'this is a title';
  WriteLn('  原始文本: ', titleText);
  WriteLn('  标题格式: ', titleText.ToTitleCase);
  
  WriteLn;
  
  // 3. 为Integer类型添加助手方法
  WriteLn('3. 为Integer类型添加助手方法:');
  var number: Integer := 10;
  WriteLn('  数字: ', number);
  WriteLn('  是偶数: ', number.IsEven);
  WriteLn('  是奇数: ', number.IsOdd);
  WriteLn('  阶乘: ', number.Factorial);
  WriteLn('  二进制: ', number.ToBinary);
  WriteLn('  是质数: ', number.IsPrime);
  
  WriteLn;
  number := 17;
  WriteLn('  数字: ', number);
  WriteLn('  是偶数: ', number.IsEven);
  WriteLn('  是奇数: ', number.IsOdd);
  WriteLn('  阶乘: ', number.Factorial);
  WriteLn('  二进制: ', number.ToBinary);
  WriteLn('  是质数: ', number.IsPrime);
  
  WriteLn;
  
  // 4. 多个助手方法的组合使用
  WriteLn('4. 多个助手方法的组合使用:');
  var sentence: String := 'pascal is awesome';
  WriteLn('  原始句子: ', sentence);
  WriteLn('  单词数: ', sentence.WordCount);
  WriteLn('  标题格式: ', sentence.ToTitleCase);
  WriteLn('  反转后: ', sentence.Reverse);
  
  WriteLn;
  
  // 5. 数字处理示例
  WriteLn('5. 数字处理示例:');
  for var i := 1 to 10 do
  begin
    Write(i, ': ');
    if i.IsEven then
      Write('偶数 ')
    else
      Write('奇数 ');
    
    if i.IsPrime then
      Write('(质数) ');
    
    WriteLn('二进制=', i.ToBinary);
  end;
  
  WriteLn;
  WriteLn('演示了 Pascal 中类助手的各种用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.